package com.bysj.lms.Shiro;


import com.alibaba.fastjson.JSONObject;

import com.bysj.lms.common.Const;

import com.bysj.lms.utils.JwtUtil;
import com.bysj.lms.utils.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;

import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheException;

import java.util.*;
import java.util.concurrent.TimeUnit;

@Slf4j
//自定义redis缓存的实现
public class RedisCache<K,V> implements Cache<K,V> {

    String cacheKey = Const.IDENTIFY_CACHE_KEY;

    /**
     * 缓存的key名称获取为shiro:cache:account
     * @param key
     * @return java.lang.String
     */
    private String getKey(Object key) {

        return Const.IDENTIFY_CACHE_KEY + JwtUtil.getAccount(key.toString());
    }

    /**
     * 获取缓存
     */
    @Override
    public V get(K key) throws CacheException {

        log.info("shiro从缓存中获取key值[{}]",key);
        if(key == null){
            return null;
        }
        try{
            String redisCacheKey = getKey(key);
            log.info("get redisCacheKey:"+redisCacheKey);
            Object value = RedisUtil.get(redisCacheKey);
            log.info(JSONObject.toJSONString(value));
            if(value == null){
                return null;
            }
        }catch (Exception e){
            throw new CacheException(e);
        }




        return null;
    }

    /**
     * 保存缓存
     */
    @Override
    public V put(K key, V value) throws CacheException {
        log.info("put ke [{}]",key);
        if(key == null){
            log.warn("Saving a null key is meaningless, return value directly without call Redis.");
            return value;
        }
        try{
            String redisCacheKey = getKey(key);
            RedisUtil.set(redisCacheKey,value!=null?value:null,24,TimeUnit.HOURS);
            log.info("redisCacheKey========="+redisCacheKey);
            log.info("value============"+value.getClass().getName());
            log.info("value============"+JSONObject.toJSONString(value));
            return value;
        }catch (Exception e){
            throw new CacheException(e);
        }
    }

    /**
     * 移除缓存
     */
    @Override
    public V remove(Object key) throws CacheException {
        log.info("remove key [{}]",key);
        if(key == null){
            return null;
        }
        try{
            String redisCacheKey = getKey(key);
            Object value = RedisUtil.get(redisCacheKey);
            V previous = (V) value;
            RedisUtil.del(redisCacheKey);
            return previous;
        }catch (Exception e){
            throw new CacheException(e);
        }
    }

    /**
     * 清空所有缓存
     */
    @Override
    public void clear() throws CacheException {
        log.debug("clear cache");
        Set<String> keys = null;
        try {
            keys = RedisUtil.keys(this.cacheKey + "*");
        } catch (Exception e) {
            log.error("get keys error", e);
        }
        if (keys == null || keys.size() == 0) {
            return;
        }
        for (String key: keys) {
            RedisUtil.del(key);
        }
    }

    /**
     * 缓存的个数
     */
    @Override
    public int size() {
        int result = 0;
        try {
            result = RedisUtil.keys(this.cacheKey + "*").size();
        } catch (Exception e) {
            log.error("get keys error", e);
        }
        return result;
    }

    /**
     * 获取所有的key
     */
    @Override
    public Set keys() {
        Set<String> keys = null;
        try {
            keys = RedisUtil.keys(this.cacheKey + "*");
        } catch (Exception e) {
            log.error("get keys error", e);
            return Collections.emptySet();
        }
        if (CollectionUtils.isEmpty(keys)) {
            return Collections.emptySet();
        }
        Set<K> convertedKeys = new HashSet<>();
        for (String key:keys) {
            try {
                convertedKeys.add((K) key);
            } catch (Exception e) {
                log.error("deserialize keys error", e);
            }
        }
        return convertedKeys;
    }

    /**
     * 获取所有的value
     */
    public Collection<V> values() {
        Set<String> keys = null;
        try {
            keys = RedisUtil.keys(this.cacheKey + "*");
        } catch (Exception e) {
            log.error("get values error", e);
            return Collections.emptySet();
        }
        if (CollectionUtils.isEmpty(keys)) {
            return Collections.emptySet();
        }
        List<V> values = new ArrayList<V>(keys.size());
        for (String key : keys) {
            V value = null;
            try {
                value = (V) RedisUtil.get(key);
            } catch (Exception e) {
                log.error("deserialize values= error", e);
            }
            if (value != null) {
                values.add(value);
            }
        }
        return Collections.unmodifiableList(values);
    }
}
